#include "Irp.h"

HANDLE g_hPipe;

NTSTATUS IrpGeneral(IN struct _DEVICE_OBJECT* DeviceObject, IN OUT struct _IRP* Irp)
{
    UNREFERENCED_PARAMETER(DeviceObject);
    UNREFERENCED_PARAMETER(Irp);
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS IrpDeviceControl(IN struct _DEVICE_OBJECT* DeviceObject, IN OUT struct _IRP* Irp)
{
    UNREFERENCED_PARAMETER(DeviceObject);

    NTSTATUS ntStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION pStackLocation = IoGetCurrentIrpStackLocation(Irp);
    ULONG uCode = pStackLocation->Parameters.DeviceIoControl.IoControlCode;
    OBJECT_ATTRIBUTES ObjectArts = { 0 };
    IO_STATUS_BLOCK IoStatusBlock = { 0 };
    UNICODE_STRING usPipeName = { 0 };
    CHAR strBuff[100] = { 0 };
    static int i = 0;

    switch (uCode)
    {
    case CTL_CODE_INIT:
    {
        if (g_hPipe)
        {
            ZwClose(g_hPipe);
            g_hPipe = NULL;
        }

        RtlInitUnicodeString(&usPipeName, USTRING_NAMED_PIPE);
        InitializeObjectAttributes(&ObjectArts, &usPipeName, OBJ_KERNEL_HANDLE, 0, 0);
        ntStatus = ZwCreateFile(&g_hPipe, FILE_WRITE_DATA | SYNCHRONIZE, &ObjectArts, &IoStatusBlock, NULL, 0, 0,
            FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE, NULL, 0);
        if (STATUS_SUCCESS != ntStatus)
        {
            ERRPRINT(ZwCreateFile, ntStatus);
        }

        break;
    }
    case CTL_CODE_GETMSG:
    {
        RtlStringCbPrintfA(strBuff, 100, "Helloworld%d", i++);
        ntStatus = ZwWriteFile(g_hPipe, 0, NULL, NULL, &IoStatusBlock, strBuff, sizeof(strBuff), NULL, NULL);
        if (STATUS_SUCCESS != ntStatus)
        {
            ERRPRINT(ZwWriteFile, ntStatus);
        }

        break;
    }
    default:
        ASSERTMSG(FALSE, __FUNCTION__);
        break;
    }

    Irp->IoStatus.Status = IoStatusBlock.Status;
    Irp->IoStatus.Information = IoStatusBlock.Information;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return ntStatus;
}
